This document provides a comprehensive guide to creating a wide variety of tables in R, from simple static tables to complex, interactive, and publication-ready displays. We will explore several powerful packages, each with its own strengths.

1 1. gt: For Beautiful, Presentation-Ready Tables

The gt package is designed for creating beautiful and highly customizable tables. It follows a “grammar of tables” philosophy, allowing you to build a table layer by layer, from the data to the header, footer, and cell formatting. This makes it ideal for tables in reports, presentations, and publications where appearance and clarity are paramount.

This example demonstrates how to create a rich, informative table from the sp500 dataset included with gt.

Code
library(gt)
library(tidyverse)
library(glue)

# Define the start and end dates for the data range
start_date <- "2010-06-07"
end_date <- "2010-06-14"

# Create a gt table from preprocessed sp500 data
sp500 |>
  filter(date >= start_date & date <= end_date) |>
  select(-adj_close) |>
  gt() |>
  # Add a title and subtitle using markdown for formatting
  tab_header(
    title = md("**S&P 500 Daily Prices**"),
    subtitle = glue("Data from {start_date} to {end_date}")
  ) |>
  # Format columns for currency, dates, and large numbers
  fmt_currency(columns = c(open, high, low, close)) |>
  fmt_date(columns = date, date_style = "wd_m_day_year") |>
  fmt_number(columns = volume, suffixing = TRUE) |>
  # Add a source note with a link
  tab_source_note(
    source_note = html("Source: <a href='https://www.spglobal.com/'>S&P Global</a>")
  ) |>
  # Center-align all columns
  cols_align(
    align = "center",
    columns = everything()
  ) |>
  # Add a color scale to the `close` column to highlight values
  data_color(
    columns = close,
    colors = scales::col_numeric(
      palette = c("#FEEBDB", "#FDD8B0", "#FDC686", "#FDB35B", "#FD9F2C"),
      domain = range(sp500$close)
    )
  )
S&P 500 Daily Prices
Data from 2010-06-07 to 2010-06-14
date open high low close volume
Mon, Jun 14, 2010 $1,095.00 $1,105.91 $1,089.03 $1,089.63 4.43B
Fri, Jun 11, 2010 $1,082.65 $1,092.25 $1,077.12 $1,091.60 4.06B
Thu, Jun 10, 2010 $1,058.77 $1,087.85 $1,058.77 $1,086.84 5.14B
Wed, Jun 9, 2010 $1,062.75 $1,077.74 $1,052.25 $1,055.69 5.98B
Tue, Jun 8, 2010 $1,050.81 $1,063.15 $1,042.17 $1,062.00 6.19B
Mon, Jun 7, 2010 $1,065.84 $1,071.36 $1,049.86 $1,050.47 5.47B
Source: S&P Global

2 2. DT: For Interactive Data Exploration

The DT package provides an R interface to the powerful JavaScript library DataTables. It turns a standard R data frame into an interactive HTML table that supports live filtering, pagination, sorting, and exporting. It is perfect for data exploration in R Markdown documents and Shiny apps.

Code
library(DT)

This is a basic example of an interactive table using the iris dataset.

Code
iris |> datatable(options = list(pageLength = 5, scrollX = TRUE))

2.0.1 Advanced Formatting and Styling

DT allows for extensive styling using the format*() family of functions. You can add color bars, conditional formatting, and more.

Code
# Take a sample of the iris dataset for a cleaner look
sample_iris <- iris[c(1:5, 51:55, 101:105), ]

sample_iris |> 
  datatable(options = list(pageLength = 5)) %>% 
  # Bold the Sepal.Length for values > 5
  formatStyle('Sepal.Length', fontWeight = styleInterval(5, c('normal', 'bold'))) %>% 
  # Apply conditional colors to Sepal.Width
  formatStyle(
    'Sepal.Width',
    color = styleInterval(c(3.0, 3.5), c('red', 'orange', 'green')),
    backgroundColor = styleInterval(3.0, c('lightgray', 'lightyellow'))
  ) %>% 
  # Add a background color bar to Petal.Length
  formatStyle(
    'Petal.Length',
    background = styleColorBar(range(iris$Petal.Length), 'steelblue'),
    backgroundSize = '100% 90%',
    backgroundRepeat = 'no-repeat',
    backgroundPosition = 'center'
  ) %>% 
  # Style the Species column
  formatStyle(
    'Species',
    backgroundColor = styleEqual(
      unique(iris$Species), c('lightblue', 'lightgreen', 'lightpink')
    )
  )

2.0.2 Table Export Buttons

The Buttons extension adds buttons to the table for exporting the data to formats like CSV, Excel, and PDF, or for copying to the clipboard.

Code
iris |> datatable(
  extensions = 'Buttons', 
  options = list(
    dom = 'Bfrtip', # Defines the layout, B is for buttons
    buttons = c('copy', 'csv', 'excel', 'pdf', 'print'),
    pageLength = 5
  )
)

3 3. reactable: For Modern and Feature-Rich Interactive Tables

reactable is another excellent package for creating interactive tables, known for its modern look, rich feature set, and ease of use. It supports sorting, filtering, grouping, and aggregation out of the box.

Code
library(reactable)
library(reactablefmtr)

mtcars %>% 
  rownames_to_column("car_name") %>% 
  select(car_name, mpg, cyl, hp, gear) %>% 
  reactable(
    filterable = TRUE, # Add column filters
    searchable = TRUE,   # Add a global search box
    groupBy = "cyl",     # Group by number of cylinders
    columns = list(
      hp = colDef(aggregate = "mean", format = colFormat(digits = 1)), # Show mean HP for each group
      gear = colDef(aggregate = "max"), # Show max gears for each group
      # Custom cell rendering to add a bar chart for mpg
      mpg = colDef(cell = data_bars(., text_position = "above", box_shadow = TRUE))
    ),
    defaultPageSize = 10
  ) %>% 
  add_title(title = 'MTCars Dataset Summary') %>% 
  add_subtitle(subtitle = 'Grouped by Cylinders', font_weight = 'normal')

MTCars Dataset Summary

Grouped by Cylinders

4 4. knitr::kable: For Simple, Static Tables

knitr::kable() is a simple and lightweight function for creating clean, static tables in various formats like HTML, LaTeX, and Markdown. It’s perfect for quick reports and documents where interactivity is not needed. The kableExtra package adds many styling options.

Code
library(knitr)
library(kableExtra)

mtcars %>% 
  head() %>% 
  kable(caption = "A Simple Static Table with kable") %>% 
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = F)
A Simple Static Table with kable
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6 160 110 3.90 2.620 16.46 0 1 4 4
Mazda RX4 Wag 21.0 6 160 110 3.90 2.875 17.02 0 1 4 4
Datsun 710 22.8 4 108 93 3.85 2.320 18.61 1 1 4 1
Hornet 4 Drive 21.4 6 258 110 3.08 3.215 19.44 1 0 3 1
Hornet Sportabout 18.7 8 360 175 3.15 3.440 17.02 0 0 3 2
Valiant 18.1 6 225 105 2.76 3.460 20.22 1 0 3 1

For longer tables, rmarkdown::paged_table() creates a scrollable, paged version, which is more user-friendly than a very long static table.

Code
library(rmarkdown)
mtcars %>% paged_table()

5 5. flextable: For Publication-Ready Tables in Office Documents

The flextable package is designed to create tables for reporting, with a focus on producing high-quality output for Microsoft Word, PowerPoint, and HTML documents. It offers a high degree of control over formatting, including cell merging, borders, and fonts.

Code
library(flextable)

# Create a basic flextable
ft <- flextable(head(mtcars))

# Apply formatting
ft <- ft %>% 
  set_header_labels(mpg = "Miles per Gallon", cyl = "Cylinders") %>% 
  theme_booktabs() %>% 
  autofit() %>% 
  set_caption("A Publication-Ready Table with flextable") %>% 
  color(j = ~ mpg, color = "red") %>% 
  bold(j = ~ cyl, bold = TRUE)

ft

Miles per Gallon

Cylinders

disp

hp

drat

wt

qsec

vs

am

gear

carb

21.0

6

160

110

3.90

2.620

16.46

0

1

4

4

21.0

6

160

110

3.90

2.875

17.02

0

1

4

4

22.8

4

108

93

3.85

2.320

18.61

1

1

4

1

21.4

6

258

110

3.08

3.215

19.44

1

0

3

1

18.7

8

360

175

3.15

3.440

17.02

0

0

3

2

18.1

6

225

105

2.76

3.460

20.22

1

0

3

1

6 6. Conclusion: Which Package Should You Use?

  • For beautiful, static reports and publications: Use gt.
  • For interactive data exploration in R Markdown or Shiny: Use DT or reactable. reactable has a more modern feel and powerful grouping features, while DT is very mature and has a rich ecosystem of extensions.
  • For quick, simple static tables: Use knitr::kable with kableExtra for styling.
  • For reports destined for Microsoft Office (Word, PowerPoint): Use flextable.

7 7. References

Back to top